﻿<template>
  <div>
    <h2>Vue 计算属性演示</h2>

    <p>Has published books (Computed): <strong>{{ publishedBooksMessage }}</strong></p>
    <p>Has published books (Method): <strong>{{ calculateBooksMessage() }}</strong></p>

    <button @click="addBook">Add a Book</button>
    <button @click="triggerRerender">Trigger Re-render</button>

    <h3>观察：</h3>
    <p>请查看控制台来观察方法和计算属性的调用次数。</p>

    <h3>解释:</h3>
    <p>计算属性基于它们的响应式依赖进行缓存。只要依赖项未发生变化，计算属性就不会重新计算。</p>
    <p>方法每次触发重新渲染时都会被调用，无论其依赖项是否变化。</p>
    <p><strong>副作用:</strong> 计算属性应该是无副作用的，这意味着它们不应该修改数据、发起异步请求或直接操作DOM。</p>

    <h3>实践:</h3>
    <p>尝试点击 "Add a Book" 和 "Trigger Re-render" 按钮，观察控制台中方法和计算属性调用次数的变化。</p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      author: {
        name: 'John Doe',
        books: ['Vue 2 - Advanced Guide'],
      },
      rerenderTrigger: 0, // 这个属性用来触发重新渲染，但不影响计算属性
    }
  },
  computed: {
    publishedBooksMessage() {
      // 计算属性不依赖 rerenderTrigger，所以修改 rerenderTrigger 不会导致重新计算
      console.log('Computing publishedBooksMessage...');
      return this.author.books.length > 0 ? 'Yes' : 'No'
    }
  },
  methods: {
    calculateBooksMessage() {
      // 由于每次组件渲染都会调用方法，方法会根据渲染次数增加调用次数
      console.log('Executing calculateBooksMessage method...');
      return this.author.books.length > 0 ? 'Yes' : 'No'
    },
    addBook() {
      this.author.books.push(`New Book ${this.author.books.length + 1}`);
      console.log('Book added, total books:', this.author.books.length);
    },
    triggerRerender() {
      this.rerenderTrigger++; // 修改这个属性将触发重新渲染，但不影响计算属性
      console.log('Re-render triggered.');
    }
  }
}
</script>

<style scoped>
</style>
